
void initPWM()
{
    ledcSetup(0, freq, resolution);  // PWM初始化
    ledcAttachPin(PWM_PIN, mos_pwm); // 绑定PWM通道

    ledcSetup(fan_pwm, freq, resolution); // PWM初始化
    ledcAttachPin(fan_PIN, fan_pwm);      // 绑定PWM通道

    ledcWrite(mos_pwm, 0); // PWM占空比初始化
    ledcWrite(fan_pwm, 0); // PWM占空比初始化

    pinMode(SD_PIN, OUTPUT);  // 设置引脚为 输出模式
    pinMode(tyn_PIN, OUTPUT); // 设置引脚为 输出模式

    digitalWrite(SD_PIN, LOW);
    digitalWrite(tyn_PIN, LOW);
}

void qidong_tiaoyaqi()
{
    if (in && adc == 0)
    {
        if (xdc_U <= Ux && tyn_U >= Utg && tyn_I <= It)
        {
            Duty++;
            if (Duty >= maxpwmvalue)
            {
                Duty = maxpwmvalue;
            }
        }
        else
        {
            Duty--;
            if (Duty <= 0)
            {
                Duty = 0;
            }
        }
        if (xdc_U > Ux * 1.02) // 如果输出电压高于设定电压 %2 关闭输出
        {
            Duty = 0;
        }
        ledcWrite(mos_pwm, Duty); // 设置 PWM 输出的占空比
    }
}
unsigned long preHeartTick4 = 0; // 心跳

void qidong_mppt()
{
    static float A;
    static float B;
    static bool C = false;
    if (mppt && in && millis() - preHeartTick4 >= 100)
    {
        if (1) // 追踪电压必须低于太阳能电压
        {
            if (xdc_U < Utg) // 追踪电压必须大于蓄电池电压
            {
                if (MOS_T < T * 1.1) // 温度保护后不再追踪最大功率
                {
                    // 进行扰动观测
                    if (C == false) // 在当前电压的基础上增加扰动步长，得到新的电压值
                    {
                        C = true;
                        Utg = Utg - s;
                        A = tyn_P;
                    }
                    else
                    {
                        C = false;
                        Utg = Utg + s;
                        B = tyn_P;
                    }
                    // 如果扰动后得到的新功率大于当前功率
                    if (A > B) // 更新当前电压为扰动后的新电压
                    {
                        Utg = Utg + s;
                    }
                    else
                    {
                        Utg = Utg - s;
                    }
                }
            }
            else
            {
                Utg = Utg + s;
            }
        }
        else
        {
            Utg = Utg - s * 100;
        }

        if (xdc_U >= Ux && xdc_I <= Ixm / 1000 && cdzt == true)
        {
            digitalWrite(spk_PIN, HIGH);
            delay(500);
            digitalWrite(spk_PIN, LOW);
            delay(500);
            digitalWrite(spk_PIN, HIGH);
            delay(500);
            digitalWrite(spk_PIN, LOW);
            Serial.println("已经冲满电,开启浮充");
            Ux = Uxf;
            cdzt = true;
        }
        else if (xdc_U <= Uxc && Ux == Uxf && cdzt == false)
        {
            digitalWrite(spk_PIN, HIGH);
            delay(500);
            digitalWrite(spk_PIN, LOW);
            delay(500);
            digitalWrite(spk_PIN, HIGH);
            delay(500);
            digitalWrite(spk_PIN, LOW);
            Serial.println("关闭浮充,开启MPPT充电模式");
            Ux = Uxm;
            cdzt = false;
        }
        preHeartTick4 = millis();
    }
}

unsigned long preHeartTick0 = 0; // 心跳
void qidongMPPT()
{
    static int ok = 0;
    if ((!out && ok == 3) || millis() - preHeartTick0 >= KEEPALIVEATIME)
    {
        if (out && tyn_U > xdc_U * 1.1)
        {
            if (ok < 3)
            {
                ok++;
            }
            if (in == false && ok == 3)
            {
                Duty = 0;
                in = true;
                Utg = tyn_U;
                Utg_max = tyn_U - 500;
                Utg_min = xdc_U + 500;

                digitalWrite(SD_PIN, HIGH);
                Serial.println("打开控制器");
                sendtoTCPServer("cmd=2&uid=" + UID + "&topic=" + TOPIC + "&msg=打开控制器\r\n"); // 推送消息
            }
        }
        else if (!out || (tyn_U < xdc_U * 0.9 && tyn_I == 0))
        {
            if (ok > 0)
            {
                if (!out)
                {
                    ok = 0;
                }
                else
                {
                    ok--;
                }
            }
            if (in == true && ok == 0)
            {
                in = false;
                digitalWrite(SD_PIN, LOW);
                digitalWrite(tyn_PIN, LOW);
                Serial.println("关闭控制器");
                sendtoTCPServer("cmd=2&uid=" + UID + "&topic=" + TOPIC + "&msg=关闭控制器\r\n"); // 推送消息
            }
        }

        int mos_pwm = map(MOS_T * 1000, T * 0.9 * 1000, T * 1.1 * 1000, 0, maxpwmvalue);       // 计算温度占空比
        ledcWrite(fan_pwm, mos_pwm < 0 ? 0 : (mos_pwm > maxpwmvalue ? maxpwmvalue : mos_pwm)); // 设置风扇占空比
        Ux = Uxm + xdc_I / 100;                                                                // 线损补偿电压
        digitalWrite(tyn_PIN, tyn_I > 0 ? HIGH : LOW);                                         // 当电流大于2安时导通太阳能输入MOS管

        preHeartTick0 = millis();
    }
    qidong_tiaoyaqi();
    qidong_mppt();
}